package com.tg.message.msg;

import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.drawable.AnimationDrawable;
import android.os.Environment;
import android.util.AttributeSet;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.RelativeLayout;

import androidx.annotation.Nullable;

import com.demo.view.ScaleGestureImageView;
import com.magicindicator.buildins.UIUtil;
import com.tange.module.media.play.combine.MediaPlayCombination;
import com.tange.module.media.play.decoration.MediaCoverDisplay;
import com.tange.module.media.play.decoration.MediaLocalFileParser;
import com.tange.module.media.play.decoration.VideoRotation;
import com.tange.module.media.play.render.MediaPlayRenderListener;
import com.tange.module.media.source.impl.CloudMediaSource;
import com.tange.module.media.source.state.CloudMediaSourceState;
import com.tange.base.toolkit.DateUtil;
import com.tg.appcommon.android.TGLog;
import com.tg.data.bean.DeviceItem;
import com.tg.message.R;

import java.io.File;

public class MessagePlayerView extends FrameLayout {

    private static final String TAG = "MessagePlayerView";

    /** 一共下载6个文件 */
    private static final int MAX_DOWNLOAD_TIME = 6;
    /** 间隔5秒下载一个文件 */
    private static final int FILE_TIME_INTERVAL = 5000;

    private String sdDirPath = Environment.getExternalStorageDirectory()
            + File.separator + Environment.DIRECTORY_DCIM;

    private View rootView;
    private View back;
    private View topBarView;
    private ImageView cover;
    private FrameLayout playerViewContainer;
    private ImageView loadingView;
    private View replayLayout;
    private View replayBtn;
    private ImageButton btnFullScreen;

    private boolean isLand = false;

    private MessageDataHolder messageDataHolder;

    private MediaCoverDisplay mediaCoverDisplay;
    private CloudMediaSource cloudMediaSource;
    private MediaPlayCombination playCombination;

    private long eventTime = 0;
    private int downloadCount = 0;

    private boolean resizeBefore = false;

    private OnVideoReadyListener onVideoReadyListener;

    private MediaLocalFileParser mediaLocalFileParser;
    private ImageButton imageFullScreen;

    private boolean isFullScreen = false;

    private RelativeLayout.LayoutParams fullRootViewLayoutParams;
    private RelativeLayout.LayoutParams fullImageLayoutParams;
    public interface OnVideoReadyListener {
        void onVideoReady();
    }

    public void setOnVideoReadyListener(OnVideoReadyListener onVideoReadyListener) {
        this.onVideoReadyListener = onVideoReadyListener;
    }

    public MessagePlayerView(Context context) {
        this(context, null);
    }

    public MessagePlayerView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MessagePlayerView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        initView(context);
    }

    private boolean isReverse(DeviceItem deviceItem) {
        if (deviceItem == null) return false;

        int rotation =  VideoRotation.getRotation(deviceItem.abilities);

        return rotation == 90 || rotation == 270;
    }

    private void initPlayer() {

        if (cloudMediaSource == null) {

            cloudMediaSource = new CloudMediaSource(
                    getContext(),
                    messageDataHolder.getDesKey(),
                    messageDataHolder.getDeviceItem().id,
                    messageDataHolder.getEventMessage().getOssid());

            cloudMediaSource.setFirstFrameListener(() -> {
                TGLog.i(TAG, "[onFirstFrame-Receive] create -> receive total time = " + (System.currentTimeMillis() - MessagePlayActivity.pageStart) + " ms");
                hideReplay();
                hideLoading(false);
            });

            cloudMediaSource.enableCache(true);

            cloudMediaSource.setMediaSourceStateListener(status -> {
                TGLog.i(TAG, "[onStatus] status = " + status);

                // 上一个文件下载成功，或者文件不存在，开始下载下一个文件
                if (status == CloudMediaSourceState.DOWNLOAD_SUCCESS || status == CloudMediaSourceState.DOWNLOAD_FILE_NOT_FOUND) {
                    requestNextCloudFile();
                }
            });

            mediaLocalFileParser = new MediaLocalFileParser(getContext(), messageDataHolder.getDesKey());

            playCombination = new MediaPlayCombination(getContext(), DeviceItem.createBasicDevice(messageDataHolder.getDeviceItem()), cloudMediaSource);
            if (!isReverse(messageDataHolder.getDeviceItem())){
                playCombination.setScaleType(MediaPlayCombination.SCALE_TYPE_FILL_PARENT);
            }

            playCombination.setMediaPlayRenderListener(new MediaPlayRenderListener() {
                @Override
                public void onVideoFirstFrameRendered() {
                    TGLog.i(TAG, "[onFirstFrame-Render] create -> render total time = " + (System.currentTimeMillis() - MessagePlayActivity.pageStart) + " ms");
                    hideCover();
                }

                @Override
                public void onVideoSizeChanged(int width, int height, boolean reverse) {
                    TGLog.i(TAG, "[onVideoSizeDecoded] " + width + "x" + height + " , reverse = " + reverse);
                    if (resizeBefore) {
                        TGLog.i(TAG, "[onVideoSizeChanged] resize before, ignore");
                        return;
                    }
                    if (reverse) {
                        resizeRootView(height, width);
                    } else {
                        resizeRootView(width, height);
                    }
                }

                @Override
                public void onVideoPlayStateChanged(boolean isStart) {
                    TGLog.i(TAG, "[onVideoPlayStateChanged] isStart = " + isStart);
                    if (!isStart) {
                        showReplay();
                    }
                }


            });
            playCombination.attachMainVideoToView(playerViewContainer, new FrameLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, Gravity.CENTER));
            playCombination.create();
        }

        if (messageDataHolder.shouldDownloadVideo()) {
            String format = "yyyy-MM-dd HH:mm:ss";
            eventTime = DateUtil.string2Millis(messageDataHolder.getEventMessage().getStart_time(), format) - 3 * 1000;
            downloadCount = 0;
            showLoading();
            requestNextCloudFile();
        }
    }

    private void requestNextCloudFile() {
        if (eventTime == 0) return;
        if (downloadCount < MAX_DOWNLOAD_TIME) {
            long next = eventTime + downloadCount * FILE_TIME_INTERVAL;
            TGLog.i(TAG, "[requestNextCloudFile] next = " + next);
            cloudMediaSource.submit(next);
            downloadCount++;
        } else {
            TGLog.i(TAG, "[requestNextCloudFile] reach max count.");
            hideLoading(true);

            // 通知外部，视频数据下好了
            if (cloudMediaSource.hasCache() && onVideoReadyListener != null) {
                mediaLocalFileParser.setCallback(new MediaLocalFileParser.Callback() {
                    @Override
                    public void onFinish() {
                        onVideoReadyListener.onVideoReady();
                    }
                });
                mediaLocalFileParser.submit(cloudMediaSource.cache());
            }
        }
    }

    public boolean saveCover() {
        if (playCombination == null) {
            return false;
        }

        if (mediaCoverDisplay != null && mediaCoverDisplay.downloaded()) {
            File f = new File(sdDirPath, System.currentTimeMillis() + ".jpg");
            return mediaCoverDisplay.export(f.getAbsolutePath());
        } else {
            return false;
        }
    }

    public boolean saveVideo() {
        if (playCombination == null) {
            return false;
        }

        if (mediaLocalFileParser.screenRecord().isCacheReady()) {
            File f = new File(sdDirPath, System.currentTimeMillis() + ".mp4");
            return mediaLocalFileParser.screenRecord().export(f.getAbsolutePath());
        } else {
            return false;
        }
    }

    private void hideCover() {
        if (cover.getVisibility() == View.VISIBLE) {
            cover.postDelayed(new Runnable() {
                @Override
                public void run() {
                    imageFullScreen.setVisibility(GONE);
                    cover.setVisibility(GONE);
                }
            }, 100);
        }
    }

    public void refresh(MessageDataHolder messageDataHolder) {
        TGLog.i(TAG, "[refresh] ... ");
        this.messageDataHolder = messageDataHolder;
        initPlayer();
        showCover();
    }

    private void replay() {
        hideCover();
        hideLoading(false);
        hideReplay();

        cloudMediaSource.decodeCache();
    }

    private void hideReplay() {
        TGLog.i(TAG, "[hideReplay] ");
        if (replayLayout.getVisibility() == View.VISIBLE) {
            replayLayout.post(() -> replayLayout.setVisibility(GONE));
        }
    }

    private void showReplay() {
        TGLog.i(TAG, "[showReplay] ");
        replayLayout.postDelayed(() -> {
            replayLayout.setVisibility(VISIBLE);
        }, 0);
    }

    public void resume() {
        TGLog.i(TAG, "resume: ");

        if (playCombination != null) {
            playCombination.resume();
        }

        if (cloudMediaSource != null && cloudMediaSource.hasCache()) {
            showReplay();
        }
    }

    public void pause() {
        TGLog.i(TAG, "[pause]");
        if (playCombination != null) {
            playCombination.pause();
        }
    }

    public void destroy() {
        TGLog.i(TAG, "[destroy]");
        if (playCombination != null) {
            playCombination.destroy();
        }
    }

    private void showCover() {
        TGLog.i(TAG, "[showCover]");
        
        if (messageDataHolder == null || messageDataHolder.getEventMessage() == null || messageDataHolder.getEventMessage().getImage_path() == null) {
            TGLog.i(TAG, "[showCover] empty cover!");
            return;
        }

        mediaCoverDisplay = new MediaCoverDisplay((Activity) getContext(), cover, DeviceItem.createBasicDevice(messageDataHolder.getDeviceItem()), messageDataHolder.getEventMessage().getImage_path());
        mediaCoverDisplay.setCallback(new MediaCoverDisplay.Callback() {
            @Override
            public void onSuccess(Bitmap bitmap, boolean reverse) {
                TGLog.i(TAG, "[showCover][onSuccess] " + bitmap.getWidth() + "x" + bitmap.getHeight() + " , reverse = " + reverse);

                if (reverse) {
                    resizeRootView(bitmap.getHeight(), bitmap.getWidth());
                } else {
                    resizeRootView(bitmap.getWidth(), bitmap.getHeight());
                }
                resizeBefore = true;
            }

            @Override
            public void onFailed() {
                cover.setVisibility(View.GONE);
                imageFullScreen.setVisibility(GONE);
            }
        });

        mediaCoverDisplay.load();

        cover.setVisibility(View.VISIBLE);
        cover.setScaleType(ImageView.ScaleType.FIT_XY);
        imageFullScreen.setVisibility(messageDataHolder != null && messageDataHolder.isPay() ? GONE : VISIBLE);
        topBarView.setVisibility(VISIBLE);
    }


    private void initView(Context context) {
        TGLog.i(TAG, "[initView] start: ");
        View view = LayoutInflater.from(context).inflate(R.layout.layout_message_player, this);
        rootView = view.findViewById(R.id.message_play_layout_inside);

        imageFullScreen = view.findViewById(R.id.btn_image_player_screen);

        topBarView = view.findViewById(R.id.player_title_view);
        back = view.findViewById(R.id.back_player);
        back.setOnClickListener(v -> onBackPressed());

        cover = view.findViewById(R.id.cover);

        playerViewContainer = view.findViewById(R.id.player_container);

        loadingView = view.findViewById(R.id.loading);

        replayLayout = view.findViewById(R.id.replay_bg);
        replayBtn = view.findViewById(R.id.replay);
        replayBtn.setOnClickListener(v -> {
            replay();
        });

        btnFullScreen = view.findViewById(R.id.btn_camera_player_screen);
        btnFullScreen.setOnClickListener(v -> {
            Activity activity = (Activity) getContext();
            if (isLand) {
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            } else {
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            }
        });

        imageFullScreen.setOnClickListener(v -> {
            if (cover instanceof ScaleGestureImageView){
                ((ScaleGestureImageView)cover).setCanScale(true);
            }
            RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams)rootView.getLayoutParams();
            fullRootViewLayoutParams = new RelativeLayout.LayoutParams(lp);
            saveLayoutParams(lp, fullRootViewLayoutParams);

            lp.width = ViewGroup.LayoutParams.MATCH_PARENT;
            lp.height = ViewGroup.LayoutParams.MATCH_PARENT;
            rootView.setLayoutParams(lp);

            RelativeLayout.LayoutParams lpCover = (RelativeLayout.LayoutParams)cover.getLayoutParams();
            fullImageLayoutParams = new RelativeLayout.LayoutParams(lpCover);
            saveLayoutParams(lpCover, fullImageLayoutParams);
            lpCover.width = ViewGroup.LayoutParams.MATCH_PARENT;
            lpCover.height = ViewGroup.LayoutParams.MATCH_PARENT;
            lpCover.addRule(Gravity.CENTER);
            lpCover.setLayoutDirection(Gravity.CENTER);

            cover.setScaleType(ImageView.ScaleType.FIT_CENTER);
            cover.setLayoutParams(lpCover);
            imageFullScreen.setVisibility(GONE);

            isFullScreen = true;
        });
        updateTopMargin();

        resizeRootView(16, 9);

        TGLog.i(TAG, "[initView] done: ");
    }

    private void saveLayoutParams( RelativeLayout.LayoutParams oldParams,  RelativeLayout.LayoutParams newParams){
        newParams.width = oldParams.width;  // 重新设置属性值
        newParams.height = oldParams.height;
        newParams.setMarginStart(oldParams.getMarginStart());
        newParams.topMargin = oldParams.topMargin;
    }

    public void onBackPressed() {
        if (isFullScreen){
            isFullScreen = false;
            imageFullScreen.setVisibility(VISIBLE);
            if (cover instanceof ScaleGestureImageView){
                ((ScaleGestureImageView)cover).setCanScale(false);
                ((ScaleGestureImageView)cover).recovery();
            }

            rootView.setLayoutParams(fullRootViewLayoutParams);
            cover.setLayoutParams(fullImageLayoutParams);

        }else{
            if (isLand) {
                Activity activity = (Activity) getContext();
                activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
                return;
            }
            if (getContext() instanceof Activity) {
                ((Activity) getContext()).finish();
            }
        }

    }

    private void updateTopMargin() {
        int statusBarHeight = (int) getResources().getDimension(R.dimen.status_bar_height);
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            statusBarHeight = getResources().getDimensionPixelSize(resourceId);
        }

        RelativeLayout.LayoutParams lp = (RelativeLayout.LayoutParams) rootView.getLayoutParams();
        if (isLand) {
            lp.topMargin = 0;
        } else {
            lp.topMargin = statusBarHeight;
        }

        rootView.setLayoutParams(lp);
    }

    private void resizeRootView(int targetWidth, int targetHeight) {
        TGLog.i(TAG, "[resizeRootView] isLand = " + isLand);
        rootView.post(() -> {
            final boolean square = targetWidth <= targetHeight;

            // 视频父容器的宽高
            final int width = UIUtil.getScreenWidth(getContext());

            int height = square ?  width : ((int) (width * 1.0 * targetHeight / targetWidth * 1.0));

            TGLog.i(TAG, "[resizeRootView] final width = " + width);
            TGLog.i(TAG, "[resizeRootView] final height = " + height);

            ViewGroup.LayoutParams lp = rootView.getLayoutParams();
            lp.width = width;
            lp.height = height;

            rootView.setLayoutParams(lp);

            if (mediaCoverDisplay != null) {
                mediaCoverDisplay.resize();
            }

            if (playCombination != null) {
                playCombination.resizeVideoTextureView();
            }

        });
    }

    public void showLoading() {
        loadingView.setVisibility(View.VISIBLE);
        AnimationDrawable a = (AnimationDrawable) loadingView.getDrawable();
        a.start();
    }

    public void hideLoading(boolean withDelay) {
        loadingView.postDelayed(() -> {
            loadingView.setVisibility(View.GONE);
            AnimationDrawable a = (AnimationDrawable) loadingView.getDrawable();
            a.stop();
        }, withDelay? 2000 : 0);
    }

    @Override
    protected void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        isLand = newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE;
        Activity activity = (Activity) getContext();
        if (isLand) {
            activity.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
            btnFullScreen.setVisibility(GONE);
            resizeRootView(UIUtil.getScreenWidth(getContext()), UIUtil.getScreenHeight(getContext()));
        } else {
            activity.getWindow().clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
            btnFullScreen.setVisibility(VISIBLE);
        }
        updateTopMargin();
    }
}
